#include "cipher.h"
#include <cstring>


unsigned long Cipher::signature_size () noexcept {

  auto hash_size = sha::hash_size(1);

  auto encrypt_size = this->_rsa.private_encrypt_size(hash_size);
  if (!encrypt_size)
    return encrypt_size;

  return b64::decode_size(encrypt_size);
}



long Cipher::signature (void *dst, const void *src, unsigned long src_size) noexcept {

  unsigned char hash_buf[64];
  unsigned char encrypt_buf[4096];

  auto hash_size = sha_hash(hash_buf, src, src_size, 1);

  auto encrypt_size = this->_rsa.private_encrypt(encrypt_buf, hash_buf, hash_size);
  if (encrypt_size < 0)
    return encrypt_size;

  return b64::encode(dst, encrypt_buf, (unsigned long)encrypt_size);
}



bool Cipher::verify (const void *src, unsigned long src_size, const void *signature, unsigned long sign_size) noexcept {

  unsigned char decode_buf[4096];
  unsigned char decrypt_buf[4096];
  unsigned char hash_buf[64];

  if (b64::decode_size(sign_size) > 4096)
    return false;
  auto decode_size = b64::decode(decode_buf, signature, sign_size);

  auto decrypt_size = this->_rsa.public_decrypt(decrypt_buf, decode_buf, (unsigned long)decode_size);
  if (decrypt_size < 0)
    return false;

  if (sha::hash_size(1) != (unsigned long)decrypt_size)
    return false;
  auto hash_size = sha::hash(hash_buf, src, src_size, 1);

  return memcmp(hash_buf, decrypt_buf, (unsigned long)hash_size) == 0;
}